﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using Backend;
using Backend.Packets;
using GameClient.Managers;

namespace GameClient
{
    public partial class MainForm : Form
    {
        private TcpClient m_Client;
        private NetworkStream m_Stream;
        private byte[] m_Buffer;

        private IDataStream m_DataStream;
        private PacketParser m_Parser;
        private ClientManager m_Manager;

        private bool bConnected;

        public bool Connected
        {
            get
            {
                return bConnected;
            }
            set
            {
                bConnected = value;
            }
        }

        private const string CLIENT_VERSION = "1.0.0";
        private const short RECV_BUFFER_SIZE = 1024;

        public MainForm()
        {
            InitializeComponent();
            this.Text = "Game Client Version: " + CLIENT_VERSION;

            m_Buffer = new byte[RECV_BUFFER_SIZE];

            bConnected = false;

            m_DataStream = new DataStream();
            m_DataStream.OnPacket += new Action<byte[]>(m_DataStream_OnPacket);

            m_Parser = new PacketParser();

            m_Manager = ClientManager.GetInstance();
            m_Manager.RegisterSend(Send);
            m_Manager.ServerResponse += new Action<string>(m_Manager_ServerResponse);
        }

        void m_Manager_ServerResponse(string obj)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>(m_Manager_ServerResponse), obj);
                return;
            }

            MessageBox.Show(obj, "Server Message!");
        }

        private void Send(IPacket Packet)
        {
            try
            {
                m_Stream.Write(Packet.Pack(), 0, Packet.Length);
            }
            catch (Exception Ex)
            {
                MessageBox.Show(Ex.Message + "\r\n" + Ex.StackTrace);
            }
        }

        void m_DataStream_OnPacket(byte[] obj)
        {
            m_Parser.ParsePacket(obj);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (bConnected)
            {
                MessageBox.Show("You Must Close The Current Connection First");
                return;
            }

            Connect ConnectDialog = new Connect();

            if (ConnectDialog.ShowDialog() == DialogResult.OK)
            {
                Connect(ConnectDialog.Address, ConnectDialog.Port, ConnectDialog.Login, ConnectDialog.Password);
            }
        }

        private void Connect(string IP, string Port, string Login, string Password)
        {
            try
            {
                m_Client = new TcpClient();

                m_Client.Connect(IP, int.Parse(Port));
                m_Stream = m_Client.GetStream();

                m_Stream.BeginRead(m_Buffer, 0, m_Buffer.Length, OnRecv, null);

                m_Manager.AccountMgr.RequestLogin(Login, Password);

                bConnected = true;
            }
            catch (Exception Ex)
            {
                MessageBox.Show("Could Not Connect");
            }
        }

        private void OnRecv(IAsyncResult Ar)
        {
            try
            {
                int nBytesRead = m_Stream.EndRead(Ar);

                m_DataStream.Parse(m_Buffer, nBytesRead);

                m_Stream.BeginRead(m_Buffer, 0, m_Buffer.Length, OnRecv, null);
            }
            catch (Exception Ex)
            {
                MessageBox.Show("Disconnected");
                bConnected = false;
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (!bConnected)
                return;
            try
            {
                m_Stream.Close();
                m_Client.Close();
            }
            catch (Exception Ex)
            {
            }
            finally
            {
                bConnected = false;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Chat ChatWindow = new Chat();
            ChatWindow.ShowDialog();
        }
    }
}
